﻿/*****************************************************
 * File:            OTCG_WpMethod.cs
 * Description:     Wp-Method for testing FSMs
 * By:              Ali Khalili (khalili DOT ir AT gmail DOT com)
 * Project:         Automata Learning
 * Requirements:    
 * Change log:
 *          -4 March 2013:  Initial version
 * To Do:
 *          -
 *          -
 * License:
 *****************************************************/
using System;
using System.Collections.Generic;
using System.Collections;

using SMLib.Automata.Base;
using SMLib.Base;


namespace MBT.Conformance.OfflineTesting
{
    /// <summary>
    /// Partial W-Method [To Do:implement it]
    /// <remarks>[Based on "Test Selection Based on Finite State Models (1991)"</remarks>
    /// </summary>
    public class OTCG_WpMethod<STATETYPE, TRANSITIONTYPE>
        : OTCG_WMethod<STATETYPE, TRANSITIONTYPE>
    {
        List<List<Word>> Wi;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="testModel">test model</param>
        public OTCG_WpMethod(IDiGraph<STATETYPE,TRANSITIONTYPE> testModel)
            : base(testModel)
        {
            computeStateCover = true;
        }

        /// <summary>
        /// Process the P and W to become ready for test case generatoin
        /// </summary>
        public override void Process()
        {
            if (processed)
                return;
            processed = true;

            FindTransitionCoverSet();

            List<Word> dW = ComputeCharachterizationSet(true);


            //* and now, also compute Wis
            ComputeIdentifyingSet(dW);
        }

        
        /// <summary>
        /// After generating W, we can generate the identifying set
        /// </summary>
        /// <param name="dw">list of distingishing words for each pair</param>
        void ComputeIdentifyingSet(List<Word> dw)
        {
            Wi = new List<List<Word>>();
            for (int i = 0; i < testModel.Size; i++)
            {
                List<Word> Wi_i = new List<Word>();
                Wi.Add(Wi_i);
                int N = testModel.Size;

                int index = 0;
                for (int j = 0; j < i; j++)
                {
                    index = (j * (N - 1) + j * (j + 1) / 2) + (i - j);
                    if (!Wi_i.Contains(dw[index]))
                        Wi_i.Add(dw[index]);
                }

                for (int j = i; j < testModel.Size; j++)
                {
                    index = (i * (N - 1) + i * (i + 1) / 2) + (j - i);
                    if (!Wi_i.Contains(dw[index]))
                        Wi_i.Add(dw[index]);
                }
            }
        }

        /// <summary>
        /// Instead of Generating the whole test sequences, we better generate them one by one!
        /// </summary>
        /// <returns>enumarated test cases</returns>
        public override IEnumerable TestSequences()
        {
            if (!processed)
                throw new Exception("You should first use 'Process()'!");

            //* first, Q.W
            for (int i = 0; i < this.stateCoverSet.Count; i++)
            {
                for (int j = 0; j < this.DistinguishingWords.Count; j++)
                {
                    Word testCase = stateCoverSet[i].Clone();
                    testCase.AddWord(DistinguishingWords[j]);
                    yield return testCase;
                }
            }

            //* then, (P-Q).Omega
            for (int i = 0; i < this.transitionCoverSet.Count; i++)
            {
                if (stateCoverSet.Contains(transitionCoverSet[i]))
                    continue;

                for (int j = 0; j < this.Wi.Count; j++)
                {
                    Word testCase = stateCoverSet[i].Clone();
                    yield return testCase;
                }
            }
        }
    }
}
